﻿using System;
using System.Collections.Generic;
using System.Text;
using Newtonsoft.Json;
using StackExchange.Redis;
using ZL.Web.Utility.Config;


namespace ZL.Web.Utility.Cache
{
    /// <summary>
    /// Redis操作类
    /// </summary>
    public class SERedisHelper
    {
        #region string类型
        /// <summary>
        /// 根据Key获取值
        /// </summary>
        /// <param name="key">键值</param>
        /// <returns>System.String.</returns>
        public static string StringGet(string key)
        {
            try
            {
             
                using (var client = ConnectionMultiplexer.Connect(ZLConfig.SERedis))
                {
                    //client.GetServer("","").Keys()
                    //foreach (var key in client.GetDatabase().Keys(pattern: "*foo*"))
                    //{
                    //    Console.WriteLine(key);
                    //}
                    return client.GetDatabase().StringGet(key);
                }
            }
            catch (Exception)
            {
                return null;
            }
        }

        /// <summary>
        /// 批量获取值
        /// </summary>
        public static string[] StringGetMany(string[] keyStrs)
        {
            var count = keyStrs.Length;
            var keys = new RedisKey[count];
            var addrs = new string[count];

            for (var i = 0; i < count; i++)
            {
                keys[i] = keyStrs[i];
            }
            try
            {
                using (var client = ConnectionMultiplexer.Connect(ZLConfig.SERedis))
                {
                    var values = client.GetDatabase().StringGet(keys);
                    for (var i = 0; i < values.Length; i++)
                    {
                        addrs[i] = values[i];
                    }
                    return addrs;
                }
            }
            catch (Exception)
            {
                return null;
            }
        }


        /// <summary>
        /// 单条存值
        /// </summary>
        /// <param name="key">key</param>
        /// <param name="value">The value.</param>
        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
        public static bool StringSet(string key, string value)
        {

            using (var client = ConnectionMultiplexer.Connect(ZLConfig.SERedis))
            {
                return client.GetDatabase().StringSet(key, value);
            }
        }


        /// <summary>
        /// 批量存值
        /// </summary>
        /// <param name="keysStr">key</param>
        /// <param name="valuesStr">The value.</param>
        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
        public static bool StringSetMany(string[] keysStr, string[] valuesStr)
        {
            var count = keysStr.Length;
            var keyValuePair = new KeyValuePair<RedisKey, RedisValue>[count];
            for (int i = 0; i < count; i++)
            {
                keyValuePair[i] = new KeyValuePair<RedisKey, RedisValue>(keysStr[i], valuesStr[i]);
            }
            using (var client = ConnectionMultiplexer.Connect(ZLConfig.SERedis))
            {
                return client.GetDatabase().StringSet(keyValuePair);
            }
        }

        #endregion

        /// <summary>
        /// 存值并设置过期时间
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key">key</param>
        /// <param name="t">实体</param>
        /// <param name="ts">过期时间间隔</param>
        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
        public static bool Set<T>(string key, T t, TimeSpan? ts, int db = -1)
        {
            var str = JsonConvert.SerializeObject(t);
            using (var client = ConnectionMultiplexer.Connect(ZLConfig.SERedis))
            {
                if (!client.GetDatabase(db).KeyExists(key))
                {
                    byte[] item = UTF8Encoding.UTF8.GetBytes(str);
                    return client.GetDatabase(db).StringSet(key, item, ts);
                }
            }
            return false;
        }

        public static bool DSet<T>(string key, T t, TimeSpan? ts, int db = -1)
        {
            var str = JsonConvert.SerializeObject(t);
            using (var client = ConnectionMultiplexer.Connect(ZLConfig.SERedis))
            {
                //if (client.GetDatabase(db).KeyExists(key))
                //{
                //    KeyDelete(key);
                //}
                byte[] item = UTF8Encoding.UTF8.GetBytes(str);
                return client.GetDatabase(db).StringSet(key, item, ts);
            }
            return false;
        }

        public static bool BatchSet<T>(Dictionary<string, T> keys, TimeSpan? ts, int db = -1)
        {
            IBatch Batch = null;
            using (var client = ConnectionMultiplexer.Connect(ZLConfig.SERedis))
            {
                IDatabase cdb = client.GetDatabase();
                Batch = cdb.CreateBatch();
                foreach (var kiitem in keys)
                {
                    var str = JsonConvert.SerializeObject(kiitem.Value);
                    byte[] item = UTF8Encoding.UTF8.GetBytes(str);
                    Batch.StringSetAsync(kiitem.Key, item);
                }
                Batch.Execute();
            }
            return false;
        }

        public static bool KeyExists(string key, int db = -1)
        {
            using (var client = ConnectionMultiplexer.Connect(ZLConfig.SERedis))
            {
                if (client.GetDatabase(db).KeyExists(key))
                {
                    return true;
                }
            }
            return false;
        }


        #region 泛型
        /// <summary>
        /// 存值并设置过期时间
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key">key</param>
        /// <param name="t">实体</param>
        /// <param name="ts">过期时间间隔</param>
        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
        public static bool KeyDelete(string key, int db = -1)
        {
           
            using (var client = ConnectionMultiplexer.Connect(ZLConfig.SERedis))
            {
               
               return client.GetDatabase(db).KeyDelete(key);
            }
        }

        /// <summary>
        /// 
        /// 根据Key获取值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key">The key.</param>
        /// <returns>T.</returns>
        public static T Get<T>(string key,int db=-1) where T : class
        {
            using (var client = ConnectionMultiplexer.Connect(ZLConfig.SERedis))
            {
                var BValue = client.GetDatabase(db).StringGet(key);
                if (BValue.IsNullOrEmpty) return null;
                string strValue = UTF8Encoding.UTF8.GetString(BValue);
                return string.IsNullOrEmpty(strValue) ? null : JsonConvert.DeserializeObject<T>(strValue);
            }
        }
        #endregion
    }

}
